/************************************************************************
Copyright 2003, 2004, 2005, 2006, 2007, 2008 Grid Technology Research Center,
National Institute of Advanced Industrial Science and Technology.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
************************************************************************/

package jp.aist.gtrc.plus.scheduler.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;

import jp.aist.gtrc.plus.reserve.ReserveException;

import org.apache.log4j.Logger;

public class CmdUtil {

	private static boolean logOut = false;
	private static Logger logger = null;

	public static final synchronized void showLog() {

		/*
		 * NOTE: We don't want show any log from client commands
		 * such as plus_account etc.
		 * We only make logger instance from PluS server's main().
		 */
		logOut = true;
		if (logger == null) {
			logger = Logger.getLogger(CmdUtil.class);
		}

	}

	private static void logDebug(String message) {

		if (logOut) {
			logger.debug(message);
		}

	}

	/*
	 * run external command
	 */
	private static Runtime runtime = Runtime.getRuntime();

	public static LinkedList<String> runCommand(String[] cmdArgs) throws ReserveException {

		assert(cmdArgs.length > 0);
		String cmd = TextUtil.fromArray(cmdArgs, " ");
		logDebug("RUN " + cmd);

		LinkedList<String> stdoutLines = new LinkedList<String>();
		StringBuffer stdout = new StringBuffer();

		Process proc = null;
		try {
			proc = runtime.exec(cmdArgs);
		} catch (IOException e) {
			throw new ReserveException(e.getMessage());
		}

		BufferedReader stdoutReader = null;
		try {
			stdoutReader = new BufferedReader(
					new InputStreamReader(proc.getInputStream(), "US-ASCII"));
			String line;
			while ((line = stdoutReader.readLine()) != null) {
				stdoutLines.add(line);
				logDebug("STDOUT " + line);
			}
		} catch (IOException e) {
			logDebug(e.toString());
		} finally {
			try {
				if (stdoutReader != null) {
					stdoutReader.close();
				}
			} catch (IOException e) {
				logDebug("failed to close stdoutReader: " + e.getMessage());
			}
		}

		BufferedReader stderrReader = null;
		try {
			stderrReader = new BufferedReader(
					new InputStreamReader(proc.getErrorStream(), "US-ASCII"));
			String line;
			while ((line = stderrReader.readLine()) != null) {
				stdout.append(line);
				stdout.append("\n");
				logDebug("STDERR " + line);
			}
		} catch (IOException e) {
			logDebug(e.toString());
		} finally {
			try {
				if (stderrReader != null) {
					stderrReader.close();
				}
			} catch (IOException e) {
				logDebug("failed to close stderrReader: " + e.getMessage());
			}
		}

		int ret = -1;
		try {
			/*
			 * NOTE: If stdout&stderr doesn't read before waitFor(),
			 * waitFor() will be blocked especially many lines are printed.
			 */
			ret = proc.waitFor();
		} catch (InterruptedException e) {
			throw new ReserveException(e.getMessage());
		}
		logDebug("exit code = " + ret);

		if (ret != 0) {
			String msg = stdout.toString().trim();
			throw new ReserveException("Failed to run \"" + cmd + "\"\n" + msg);
		}

		return stdoutLines;

	}

}
